<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.1.1">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/font-awesome.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"example.com","root":"/","scheme":"Gemini","version":"7.8.0","exturl":false,"sidebar":{"position":"left","width":300,"display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="本篇为Java线程池ThreadPoolExecutor学习的第一篇，也是基础篇。该篇介绍了线程池相关概念，ThreadPoolExecutor的重点属性（ctl）、五种状态、七大参数构造参数及其基础用法。">
<meta property="og:type" content="article">
<meta property="og:title" content="Java线程池之ThreadPoolExecutor（一）">
<meta property="og:url" content="http://example.com/2020/09/27/Java%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%B9%8BThreadPoolExecutor1/index.html">
<meta property="og:site_name" content="履歴の本文">
<meta property="og:description" content="本篇为Java线程池ThreadPoolExecutor学习的第一篇，也是基础篇。该篇介绍了线程池相关概念，ThreadPoolExecutor的重点属性（ctl）、五种状态、七大参数构造参数及其基础用法。">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="http://example.com/2020/09/27/Java%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%B9%8BThreadPoolExecutor1/000.png">
<meta property="og:image" content="http://example.com/2020/09/27/Java%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%B9%8BThreadPoolExecutor1/001.png">
<meta property="article:published_time" content="2020-09-27T14:22:06.000Z">
<meta property="article:modified_time" content="2020-10-08T03:39:19.944Z">
<meta property="article:author" content="モンキーDルフィ">
<meta property="article:tag" content="线程池">
<meta property="article:tag" content="多线程">
<meta property="article:tag" content="高并发">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="http://example.com/2020/09/27/Java%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%B9%8BThreadPoolExecutor1/000.png">

<link rel="canonical" href="http://example.com/2020/09/27/Java%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%B9%8BThreadPoolExecutor1/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>Java线程池之ThreadPoolExecutor（一） | 履歴の本文</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">履歴の本文</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">天下风云出我辈，一入代码岁月催</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-fw fa-home"></i>首页</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-fw fa-tags"></i>标签<span class="badge">15</span></a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-fw fa-th"></i>分类<span class="badge">7</span></a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-fw fa-archive"></i>归档<span class="badge">18</span></a>

  </li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div id="search-result">
  <div id="no-result">
    <i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
  </div>
</div>

    </div>
  </div>

</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://example.com/2020/09/27/Java%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%B9%8BThreadPoolExecutor1/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/lufei.jpg">
      <meta itemprop="name" content="モンキーDルフィ">
      <meta itemprop="description" content="海贼王におれはなる！">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="履歴の本文">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          Java线程池之ThreadPoolExecutor（一）
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-09-27 22:22:06" itemprop="dateCreated datePublished" datetime="2020-09-27T22:22:06+08:00">2020-09-27</time>
            </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/" itemprop="url" rel="index"><span itemprop="name">并发编程</span></a>
                </span>
            </span>

          
            <span id="/2020/09/27/Java%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%B9%8BThreadPoolExecutor1/" class="post-meta-item leancloud_visitors" data-flag-title="Java线程池之ThreadPoolExecutor（一）" title="阅读次数">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span class="leancloud-visitors-count"></span>
            </span>
  
  <span class="post-meta-item">
    
      <span class="post-meta-item-icon">
        <i class="fa fa-comment-o"></i>
      </span>
      <span class="post-meta-item-text">Valine：</span>
    
    <a title="valine" href="/2020/09/27/Java%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%B9%8BThreadPoolExecutor1/#valine-comments" itemprop="discussionUrl">
      <span class="post-comments-count valine-comment-count" data-xid="/2020/09/27/Java%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%B9%8BThreadPoolExecutor1/" itemprop="commentCount"></span>
    </a>
  </span>
  
  
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
              <span>6.6k</span>
            </span>
            <span class="post-meta-item" title="阅读时长">
              <span class="post-meta-item-icon">
                <i class="fa fa-clock-o"></i>
              </span>
              <span>6 分钟</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <p>本篇为Java线程池ThreadPoolExecutor学习的第一篇，也是基础篇。该篇介绍了线程池相关概念，ThreadPoolExecutor的重点属性（ctl）、五种状态、七大参数构造参数及其基础用法。</p>
<a id="more"></a>

<h2 id="The-Thread-Pool"><a href="#The-Thread-Pool" class="headerlink" title="The Thread Pool"></a>The Thread Pool</h2><p>线程池，顾名思义就是一个线程缓存。线程是稀缺资源，如果被无限制地创建，不仅会消耗系统资源，还会降低系统的稳定性，因此Java中提供线程池对线程进行统一分配、调用和监控。</p>
<h3 id="Introduction-to-Thread-Pool"><a href="#Introduction-to-Thread-Pool" class="headerlink" title="Introduction to Thread Pool"></a>Introduction to Thread Pool</h3><p>在web开发中，服务器要接受并处理请求，所以会为一个请求来分配一个线程去进行处理。如果每次请求都新创建一个线程的话实现起来非常方便，但是存在一个问题：<strong>如果并发的请求数量非常多，但每个线程执行的时间很短，这样就会频繁地创建和销毁线程，如此一来会大大降低系统的效率。可能会出现服务器在为每个请求创建新线程和销毁线程上花费的时间和消耗的系统资源要比处理实际的用户请求的时间和资源更多。</strong></p>
<p>那么有没有一种办法使线程执行完之后不被销毁，而是可以继续执行其他的任务呢？这就是线程池的目的了。线程池为线程生命周期的开销和资源不足的问题提供了解决方案。通过对多个任务重用线程，线程创建的开销被分摊到了多个任务上。</p>
<h3 id="When-To-Use-Thread-Pool"><a href="#When-To-Use-Thread-Pool" class="headerlink" title="When To Use Thread Pool"></a>When To Use Thread Pool</h3><p>什么时候使用线程池呢？</p>
<ul>
<li>单个任务处理时间比较短</li>
<li>需要处理的任务数量很大</li>
</ul>
<h3 id="Advantages-Of-Thread-Pool"><a href="#Advantages-Of-Thread-Pool" class="headerlink" title="Advantages Of Thread Pool"></a>Advantages Of Thread Pool</h3><p>线程池有以下优势：</p>
<ul>
<li>重用存在的线程，减少线程创建、销毁的开销，提升性能。</li>
<li>提高响应速度。当任务到达时，可以不用等待线程创建就能立刻执行。</li>
<li>提高线程的可管理性。线程是稀缺资源，如果被无限制地创建，不仅会消耗系统资源，还会降低系统的稳定性，使用线程池可以对线程进行统一分配、调用和监控。</li>
</ul>
<h3 id="Implementation-Of-Thread-Pool"><a href="#Implementation-Of-Thread-Pool" class="headerlink" title="Implementation Of Thread Pool"></a>Implementation Of Thread Pool</h3><p>Java中对线程池的实现有<strong>ThreadPoolExecutor</strong>（默认线程池）和<strong>ScheduledThreadPoolExecutor</strong>（定时线程池）。其中ThreadPoolExecutor最为核心，对Java线程池的学习理当以此为开始。尽管juc（java.util.concurrent）中提供了工具类Executors可以方便快速地创建各种线程池，但是我们还是应该使用ThreadPoolExecutors去手动创建。关于这点，阿里开发规范手册中有明确说明：</p>
<pre><code>线程池不允许使用 Executors 去创建，而是通过ThreadPoolExecutor的方式，这样的处理方式让写的同学更加明确线程池的运行规则，规避资源耗尽的风险。说明：Executors 返回的线程池对象的弊端如下:
1. FixedThreadPool 和 SingleThreadPool：允许的请求队列长度为 Integer.MAX_VALUE，可能会堆积大量的请求，从而导致 OOM。
2. CachedThreadPool 和 ScheduledThreadPool：允许的创建线程数量为 Integer.MAX_VALUE，可能会创建大量的线程，从而导致 OOM。</code></pre>
<h2 id="ThreadPoolExecutor"><a href="#ThreadPoolExecutor" class="headerlink" title="ThreadPoolExecutor"></a>ThreadPoolExecutor</h2><p>ThreadPoolExecutor的类继承关系图如下：<br><img src="/2020/09/27/Java%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%B9%8BThreadPoolExecutor1/000.png" alt="000"><br>Executor接口作为顶级超类，它定义了一个用于执行Runnable任务的execute方法。<br>ExecutorService作为次级超类，它又补充定义了如下一些线程池的具体行为：</p>
<ul>
<li>submit(task)：用来提交Callable或者Runnable任务，并返回代表此任务Future对象。</li>
<li>invokeAll(tasks)：执行一系列任务，全部执行完毕时返回代表各自任务的Future对象。</li>
<li>invokeAny(tasks)：执行一系列任务，当有一个执行完毕就返回该任务的Future对象。</li>
<li>shutdown()：关闭线程池，不再接管新任务，继续执行完已经提交的任务。</li>
<li>shutdownNow()：停止线程池，不再接管新任务，并且立刻停止正在执行的任务。</li>
<li>isShutdown()：判断线程池是否已经被关闭。</li>
<li>isTerminated()：判断是否所有任务都已经被执行完毕。</li>
</ul>
<h3 id="Ctl-Of-ThreadPoolExecutor"><a href="#Ctl-Of-ThreadPoolExecutor" class="headerlink" title="Ctl Of ThreadPoolExecutor"></a>Ctl Of ThreadPoolExecutor</h3><p>线程池有一个重要的属性——clt，它是一个原子整型类，如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="keyword">final</span> AtomicInteger ctl = <span class="keyword">new</span> AtomicInteger(ctlOf(RUNNIG, <span class="number">0</span>)); <span class="comment">// 表征线程池的初始状态为RUNNING，有效线程数为0</span></span><br></pre></td></tr></table></figure>
<p>该属性实际上打包了两个概念性的字段，也就是它包含了两部分的信息。其中高3为保存了线程池的运行状态（runState），后29位保存了线程池的有效线程数（workerCount）。与ctl相关的其他属性和方法如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> COUNT_BITS = Integer.SIZE - <span class="number">3</span>; <span class="comment">// 29</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> CAPACITY = (<span class="number">1</span> &lt;&lt; COUNT_BITS) - <span class="number">1</span>; <span class="comment">// 线程池容量，大约5亿</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// ctl打包、拆包相关方法</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">runStateOf</span><span class="params">(<span class="keyword">int</span> c)</span>        </span>&#123; <span class="keyword">return</span> c &amp; ~CAPACITY; &#125; <span class="comment">// 通过ctl获取运行状态</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">workerCountOf</span><span class="params">(<span class="keyword">int</span> c)</span>     </span>&#123; <span class="keyword">return</span> c &amp; CAPACITY; &#125; <span class="comment">// 通过ctl获取有效线程数</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">ctlOf</span><span class="params">(<span class="keyword">int</span> rs, <span class="keyword">int</span> ws)</span>    </span>&#123; <span class="keyword">return</span> rs | wc; &#125; <span class="comment">// 将运行状态和有效线程数打包成ctl</span></span><br></pre></td></tr></table></figure>
<p>这里，我们只需知道ctl包含的两部分信息及其打包拆包方法即可。至于那些位运算是如何巧妙地做到这些的，我们没必要细扣，重点是掌握线程池的原理。</p>
<h3 id="Five-Kinds-Of-State"><a href="#Five-Kinds-Of-State" class="headerlink" title="Five Kinds Of State"></a>Five Kinds Of State</h3><p>线程池存在五种状态，其代码表征如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> RUNNING    = -<span class="number">1</span> &lt;&lt; COUNT_BITS; <span class="comment">// 高三位111</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> SHUTDOWN   =  <span class="number">0</span> &lt;&lt; COUNT_BITS; <span class="comment">// 高三位000</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> STOP       =  <span class="number">1</span> &lt;&lt; COUNT_BITS; <span class="comment">// 高三位001</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> TIDYING    =  <span class="number">2</span> &lt;&lt; COUNT_BITS; <span class="comment">// 高三位010</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> TERMINATED =  <span class="number">3</span> &lt;&lt; COUNT_BITS; <span class="comment">// 高三位011</span></span><br></pre></td></tr></table></figure>

<h4 id="RUNNING"><a href="#RUNNING" class="headerlink" title="RUNNING"></a>RUNNING</h4><p>线程池处在“运行”状态，能够接收新的任务，以及对已经添加的任务进行处理。线程池的初始化状态就是RUNNING。换句话说，线程池一旦被创建，就处于RUNNING状态，并且线程池中的任务数位0。</p>
<h4 id="SHUTDOWN"><a href="#SHUTDOWN" class="headerlink" title="SHUTDOWN"></a>SHUTDOWN</h4><p>线程池处在“关闭”状态，不再接收新的任务，但是还能处理已经添加的任务。<strong>调用线程池的shutdown()方法时，线程池由RUNNIG -&gt; SHUTDOWN。</strong></p>
<h4 id="STOP"><a href="#STOP" class="headerlink" title="STOP"></a>STOP</h4><p>线程池处在“停止”状态，不再接收新的任务，也不能处理已经添加的任务，而且还会停止正在执行的任务。<strong>调用线程池的shutdownNow()方法时，线程池由RUNNING/SHUTDOWN -&gt; STOP。</strong></p>
<h4 id="TIDYING"><a href="#TIDYING" class="headerlink" title="TIDYING"></a>TIDYING</h4><pre><code>读音：[ˈtaɪdiɪŋ]</code></pre>
<p>线程池处在“整理”状态。当所有的任务已终止，ctl记录的“任务数量”为0时，线程池就会变为TIDYING状态。当线程池变为TIDYING状态时，会执行钩子函数terminated()。terminated()在ThreadPoolExecutor中是空实现，用户可以通过重写该方法来实现自定义的“整理”。<strong>当线程池处在SHUTDOWN状态下，阻塞队列为空并且线程池中执行的任务也为空时，就会由SHUTDOWN -&gt; TIDYING。当线程池处在STOP状态下，线程池中执行的任务为空时，就会由STOP -&gt; TIDYING。</strong></p>
<h4 id="TERMINATED"><a href="#TERMINATED" class="headerlink" title="TERMINATED"></a>TERMINATED</h4><p>线程池处在“终止”状态。线程池切换至TIDYING状态成功，并且执行完钩子函数terminated()后，状态变为TERMINATED。进入TERMINATED状态的条件如下：</p>
<ul>
<li>线程池不是RUNNING、TIDYING或者TERMINATED状态</li>
<li>如果线程池状态时SHUTDOWN并且workerQueue为空</li>
<li>workerCount为0</li>
<li>设置TIDYING成功</li>
<li>执行钩子函数terminated()成功</li>
</ul>
<p><strong>线程池的五种状态切换图如下：</strong><br><img src="/2020/09/27/Java%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%B9%8BThreadPoolExecutor1/001.png" alt="001"></p>
<h3 id="Seven-Constructal-Parameters"><a href="#Seven-Constructal-Parameters" class="headerlink" title="Seven Constructal Parameters"></a>Seven Constructal Parameters</h3><p>线程池有七大构造参数，方便我们实际情况灵活地创建合适的线程池。</p>
<h4 id="corePoolSize"><a href="#corePoolSize" class="headerlink" title="corePoolSize"></a>corePoolSize</h4><p>线程池的核心线程数。当提交一个任务时，线程池会创建一个新线程执行任务，直到当前线程数等于corePoolSize；如果当前线程数等于corePoolSize，继续提交的任务会被保存到阻塞队列中，等待被执行。如果执行了prestartAllCoreThreads()方法，线程池会提前创建并启动所有核心线程。</p>
<h4 id="maximumPoolSize"><a href="#maximumPoolSize" class="headerlink" title="maximumPoolSize"></a>maximumPoolSize</h4><p>线程池中允许的最大线程数。如果当前阻塞队列满了，且继续提交任务，则会创建新的线程执行任务，前提是当前线程数小于maximumPoolSize。</p>
<h4 id="keepAliveTime"><a href="#keepAliveTime" class="headerlink" title="keepAliveTime"></a>keepAliveTime</h4><p>线程池中维护线程所允许的最大空闲时间。当线程池中的线程数量大于corePoolSize的时候，如果这时没有新的任务提交，核心线程之外的线程不会立即销毁，而是等待，直到等待的时间超过了keepAliveTime。</p>
<h4 id="unit"><a href="#unit" class="headerlink" title="unit"></a>unit</h4><p>keepAliveTime的单位。</p>
<h4 id="workQueue"><a href="#workQueue" class="headerlink" title="workQueue"></a>workQueue</h4><p>阻塞队列，用来保存等待被执行的任务。在JDK中提供了如下几种阻塞队列：</p>
<ol>
<li>ArrayBlockingQueue：基于数组的有界阻塞队列</li>
<li>LinkedBlockingQueue：基于链表的无界阻塞队列，吞吐量通常要高于ArrayBlockingQueue</li>
<li>SynchronousQueue：一个不存储元素的阻塞队列，每个插入操作必须等到另一个线程调用移除操作，否则插入操作一直处于阻塞状态，吞吐量通常要高于LinkedBlockingQueue</li>
<li>PriorityBlockingQueue：具有优先级的无界阻塞队列</li>
</ol>
<h4 id="threadFactory"><a href="#threadFactory" class="headerlink" title="threadFactory"></a>threadFactory</h4><p>线程工厂，ThreadFactory类型变量，用来创建新线程。默认使用Executors.defaultThreadFactory()来创建线程，这些线程具有相同的优先级，并且都是非守护线程，同时也被设置了名字。</p>
<h4 id="handler"><a href="#handler" class="headerlink" title="handler"></a>handler</h4><p>线程池的饱和（拒绝）策略。当阻塞队列满了，并且线程池中的工作线程数达到了maximumPoolSize，如果继续提交任务，此时线程池无法再处理这些任务，必须通过其他的策略来进行处理。线程池提供了4中策略（ThreadPoolExecutor的内部类）：</p>
<ol>
<li>AbortPolicy：直接抛出异常，默认策略</li>
<li>CallerRunsPolicy：用调用者所在的线程来执行任务</li>
<li>DiscardOldestPolicy：丢弃阻塞队列中最靠前的任务，并执行当前任务</li>
<li>DiscardPolicy：直接丢弃任务</li>
</ol>
<p>当然也可以通过实现RejectedExecutionHandler接口来自定义饱和策略，如记录日志或者持久化存储无法处理的任务。</p>
<h3 id="Basic-Usage"><a href="#Basic-Usage" class="headerlink" title="Basic Usage"></a>Basic Usage</h3><h4 id="Construction"><a href="#Construction" class="headerlink" title="Construction"></a>Construction</h4><p>线程池提供了如下4种构造函数：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 完全自定义构造（七大参数）</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="title">ThreadPoolExecutor</span><span class="params">(<span class="keyword">int</span> corePoolSize,</span></span></span><br><span class="line"><span class="function"><span class="params">                              <span class="keyword">int</span> maximumPoolSize,</span></span></span><br><span class="line"><span class="function"><span class="params">                              <span class="keyword">long</span> keepAliveTime,</span></span></span><br><span class="line"><span class="function"><span class="params">                              TimeUnit unit,</span></span></span><br><span class="line"><span class="function"><span class="params">                              BlockingQueue&lt;Runnable&gt; workQueue,</span></span></span><br><span class="line"><span class="function"><span class="params">                              ThreadFactory threadFactory,</span></span></span><br><span class="line"><span class="function"><span class="params">                              RejectedExecutionHandler handler)</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function"><span class="comment">// 使用默认线程工厂</span></span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="title">ThreadPoolExecutor</span><span class="params">(<span class="keyword">int</span> corePoolSize,</span></span></span><br><span class="line"><span class="function"><span class="params">                              <span class="keyword">int</span> maximumPoolSize,</span></span></span><br><span class="line"><span class="function"><span class="params">                              <span class="keyword">long</span> keepAliveTime,</span></span></span><br><span class="line"><span class="function"><span class="params">                              TimeUnit unit,</span></span></span><br><span class="line"><span class="function"><span class="params">                              BlockingQueue&lt;Runnable&gt; workQueue,</span></span></span><br><span class="line"><span class="function"><span class="params">                              RejectedExecutionHandler handler)</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function"><span class="comment">// 使用默认饱和策略</span></span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="title">ThreadPoolExecutor</span><span class="params">(<span class="keyword">int</span> corePoolSize,</span></span></span><br><span class="line"><span class="function"><span class="params">                              <span class="keyword">int</span> maximumPoolSize,</span></span></span><br><span class="line"><span class="function"><span class="params">                              <span class="keyword">long</span> keepAliveTime,</span></span></span><br><span class="line"><span class="function"><span class="params">                              TimeUnit unit,</span></span></span><br><span class="line"><span class="function"><span class="params">                              BlockingQueue&lt;Runnable&gt; workQueue,</span></span></span><br><span class="line"><span class="function"><span class="params">                              ThreadFactory threadFactory)</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function"><span class="comment">// 使用默认线程工厂和饱和策略</span></span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="title">ThreadPoolExecutor</span><span class="params">(<span class="keyword">int</span> corePoolSize,</span></span></span><br><span class="line"><span class="function"><span class="params">                              <span class="keyword">int</span> maximumPoolSize,</span></span></span><br><span class="line"><span class="function"><span class="params">                              <span class="keyword">long</span> keepAliveTime,</span></span></span><br><span class="line"><span class="function"><span class="params">                              TimeUnit unit,</span></span></span><br><span class="line"><span class="function"><span class="params">                              BlockingQueue&lt;Runnable&gt; workQueue)</span></span></span><br></pre></td></tr></table></figure>
<p>手动创建线程池：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ThreadPoolExecutor threadPoolExecutor = <span class="keyword">new</span> ThreadPoolExecutor(<span class="number">5</span>, <span class="number">10</span>, <span class="number">500</span>, TimeUnit.MILLISECONDS, <span class="keyword">new</span> ArrayBlockingQueue&lt;&gt;(<span class="number">10</span>));</span><br></pre></td></tr></table></figure>
<p>关于线程池（最大）线程数的设置有以下行业经验（假设CPU的合适为N）：</p>
<ul>
<li>CPU密集型：N + 1</li>
<li>IO密集型：2N + 1</li>
</ul>
<p>更确切地来说，最佳线程数目 = （（线程等待时间+线程CPU运行时间）/线程CPU运行时间） * CPU核数。</p>
<h4 id="Submit-Task"><a href="#Submit-Task" class="headerlink" title="Submit Task"></a>Submit Task</h4><p>线程池提交任务有四种方式，如下：</p>
<ol>
<li>执行Runnable任务，没有返回值<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">threadPoolExecutor.execute(<span class="keyword">new</span> Runnable() &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="number">123</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure></li>
<li>提交Runnable任务，返回异步执行结果对象Future（具体实现为FutureTask）<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Future&lt;?&gt; submit = threadPoolExecutor.submit(<span class="keyword">new</span> Runnable() &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="number">123</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">submit.get(); <span class="comment">// 获取异步执行结果（始终为null），阻塞当前线程</span></span><br></pre></td></tr></table></figure></li>
<li>提交Runnable任务，并指定异步执行结果的返回值的默认值，返回异步执行结果对象Future（具体实现为FutureTask）<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Future&lt;String&gt; submit = threadPoolExecutor.submit(<span class="keyword">new</span> Runnable() &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="number">123</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;, <span class="string">&quot;123&quot;</span>);</span><br><span class="line"></span><br><span class="line">submit.get(); <span class="comment">// 获取异步执行结果（默认值为123），阻塞当前线程</span></span><br></pre></td></tr></table></figure></li>
<li>提交Callable任务，返回异步执行结果对象Future（具体实现为FutureTask）<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Future&lt;Integer&gt; submit = threadPoolExecutor.submit(<span class="keyword">new</span> Callable&lt;Integer&gt;() &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Integer <span class="title">call</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">123</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">submit.get(); <span class="comment">// 获取异步执行结果（手动定义），阻塞当前线程</span></span><br></pre></td></tr></table></figure></li>
</ol>

    </div>

    
    
    

      <footer class="post-footer">
          
          <div class="post-tags">
              <a href="/tags/%E7%BA%BF%E7%A8%8B%E6%B1%A0/" rel="tag"><i class="fa fa-tag"></i> 线程池</a>
              <a href="/tags/%E5%A4%9A%E7%BA%BF%E7%A8%8B/" rel="tag"><i class="fa fa-tag"></i> 多线程</a>
              <a href="/tags/%E9%AB%98%E5%B9%B6%E5%8F%91/" rel="tag"><i class="fa fa-tag"></i> 高并发</a>
          </div>

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/2020/09/26/Hexo+GitHub%E5%BF%AB%E9%80%9F%E6%90%AD%E5%BB%BA%E4%B8%AA%E4%BA%BA%E5%8D%9A%E5%AE%A23/" rel="prev" title="Hexo + Gitee快速搭建个人博客（三）">
      <i class="fa fa-chevron-left"></i> Hexo + Gitee快速搭建个人博客（三）
    </a></div>
      <div class="post-nav-item">
    <a href="/2020/10/08/Java%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%B9%8BThreadPoolExecutor2/" rel="next" title="Java线程池之ThreadPoolExecutor（二）">
      Java线程池之ThreadPoolExecutor（二） <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          
    <div class="comments" id="valine-comments"></div>

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#The-Thread-Pool"><span class="nav-number">1.</span> <span class="nav-text">The Thread Pool</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#Introduction-to-Thread-Pool"><span class="nav-number">1.1.</span> <span class="nav-text">Introduction to Thread Pool</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#When-To-Use-Thread-Pool"><span class="nav-number">1.2.</span> <span class="nav-text">When To Use Thread Pool</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Advantages-Of-Thread-Pool"><span class="nav-number">1.3.</span> <span class="nav-text">Advantages Of Thread Pool</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Implementation-Of-Thread-Pool"><span class="nav-number">1.4.</span> <span class="nav-text">Implementation Of Thread Pool</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#ThreadPoolExecutor"><span class="nav-number">2.</span> <span class="nav-text">ThreadPoolExecutor</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#Ctl-Of-ThreadPoolExecutor"><span class="nav-number">2.1.</span> <span class="nav-text">Ctl Of ThreadPoolExecutor</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Five-Kinds-Of-State"><span class="nav-number">2.2.</span> <span class="nav-text">Five Kinds Of State</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#RUNNING"><span class="nav-number">2.2.1.</span> <span class="nav-text">RUNNING</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#SHUTDOWN"><span class="nav-number">2.2.2.</span> <span class="nav-text">SHUTDOWN</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#STOP"><span class="nav-number">2.2.3.</span> <span class="nav-text">STOP</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#TIDYING"><span class="nav-number">2.2.4.</span> <span class="nav-text">TIDYING</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#TERMINATED"><span class="nav-number">2.2.5.</span> <span class="nav-text">TERMINATED</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Seven-Constructal-Parameters"><span class="nav-number">2.3.</span> <span class="nav-text">Seven Constructal Parameters</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#corePoolSize"><span class="nav-number">2.3.1.</span> <span class="nav-text">corePoolSize</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#maximumPoolSize"><span class="nav-number">2.3.2.</span> <span class="nav-text">maximumPoolSize</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#keepAliveTime"><span class="nav-number">2.3.3.</span> <span class="nav-text">keepAliveTime</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#unit"><span class="nav-number">2.3.4.</span> <span class="nav-text">unit</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#workQueue"><span class="nav-number">2.3.5.</span> <span class="nav-text">workQueue</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#threadFactory"><span class="nav-number">2.3.6.</span> <span class="nav-text">threadFactory</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#handler"><span class="nav-number">2.3.7.</span> <span class="nav-text">handler</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Basic-Usage"><span class="nav-number">2.4.</span> <span class="nav-text">Basic Usage</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#Construction"><span class="nav-number">2.4.1.</span> <span class="nav-text">Construction</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#Submit-Task"><span class="nav-number">2.4.2.</span> <span class="nav-text">Submit Task</span></a></li></ol></li></ol></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="モンキーDルフィ"
      src="/images/lufei.jpg">
  <p class="site-author-name" itemprop="name">モンキーDルフィ</p>
  <div class="site-description" itemprop="description">海贼王におれはなる！</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">18</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">7</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">15</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>



      </div>
      <iframe frameborder="no" border="0" marginwidth="0" marginheight="0" width=330 height=86 src="//music.163.com/outchain/player?type=2&id=174419&auto=1&height=66"></iframe>
    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2020</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">モンキーDルフィ</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-area-chart"></i>
    </span>
    <span title="站点总字数">66k</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-coffee"></i>
    </span>
    <span title="站点阅读时长">1:01</span>
</div>

        








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  




  
<script src="/js/local-search.js"></script>













  

  


<script>
NexT.utils.loadComments(document.querySelector('#valine-comments'), () => {
  NexT.utils.getScript('https://cdn.jsdelivr.net/npm/valine@1.4.14/dist/Valine.min.js', () => {
    var GUEST = ['nick', 'mail', 'link'];
    var guest = 'nick,mail,link';
    guest = guest.split(',').filter(item => {
      return GUEST.includes(item);
    });
    new Valine({
      el         : '#valine-comments',
      verify     : false,
      notify     : false,
      appId      : 'rp9eaSA9Y6vBrWUdOf5ukLYs-gzGzoHsz',
      appKey     : 'SIkchhA5LF0xmXpXKtbkA65H',
      placeholder: "欢迎大家前来交流~",
      avatar     : '/images/lufei.jpg',
      meta       : guest,
      pageSize   : '10' || 10,
      visitor    : true,
      lang       : 'zh-CN' || 'zh-cn',
      path       : location.pathname,
      recordIP   : false,
      serverURLs : ''
    });
  }, window.Valine);
});
</script>

</body>
</html>
